Skip to content

Comments

feat(whatsapp): add WhatsApp channel support#73

Open
penso wants to merge 24 commits intomainfrom
nanobot
Open

feat(whatsapp): add WhatsApp channel support#73
penso wants to merge 24 commits intomainfrom
nanobot

Conversation

@penso
Copy link
Collaborator

@penso penso commented Feb 9, 2026

Summary

  • Add WhatsApp as a second messaging channel via whatsapp-rust, gated behind the whatsapp cargo feature (enabled by default)
  • New moltis-whatsapp crate: QR code pairing, sled-backed Signal Protocol persistence, inbound media handling (image/voice/video/document/location), access control (DM/group policies + OTP), self-chat with loop prevention
  • Multi-channel architecture refactor: LiveChannelService with concrete plugin fields behind feature flags, MultiChannelOutbound for routing by account type
  • Gateway integration: REST/RPC routes, WebSocket pairing events, chat routing, web UI (type picker, QR modal, channel cards)
  • Documentation at docs/src/whatsapp.md

Validation

Completed

  • cargo +nightly fmt --all -- --check
  • cargo +nightly clippy --workspace --all-targets
  • cargo +nightly check
  • cargo +nightly test -p moltis-whatsapp (63 tests)
  • cargo +nightly test -p moltis-channels -p moltis-config -p moltis-gateway (337 tests)
  • biome ci crates/gateway/src/assets/js/page-channels.js
  • All 400 tests pass, 0 failures

Remaining

  • Merge main and run ./scripts/local-validate.sh with PR number
  • Manual QA: WhatsApp QR pairing flow end-to-end
  • Manual QA: WhatsApp media messages (image, voice, video, document, location)

Manual QA

Tested compilation, formatting, linting, and full test suite. End-to-end WhatsApp pairing and message flow require a physical device.

penso added 2 commits February 9, 2026 11:24
Add WhatsApp as a second messaging channel via the whatsapp-rust crate,
gated behind the `whatsapp` cargo feature (enabled by default).

New crate `moltis-whatsapp` with:
- QR code pairing through WhatsApp Linked Devices
- Sled-backed persistent Signal Protocol store (survives restarts)
- Inbound text, media (image/voice/video/document/location) handling
- Outbound text replies with typing indicators
- DM and group access control (Open/Allowlist/Disabled) with OTP flow
- Self-chat support with watermark-based loop prevention

Multi-channel architecture refactor:
- LiveChannelService now supports concrete plugin fields behind feature flags
- MultiChannelOutbound routes outbound messages by account type
- ChannelPlugin trait extended for WhatsApp lifecycle

Gateway integration:
- Channel REST/RPC routes for WhatsApp config and pairing
- Real-time pairing events over WebSocket
- Chat routing for WhatsApp inbound messages
- Web UI: channel type picker, QR code modal, WhatsApp card/edit views

Documentation and changelog updated.
Resolve conflicts: keep WhatsApp changelog entries in [Unreleased]
above the 0.3.8 release from main. Regenerate Cargo.lock.
@codspeed-hq
Copy link
Contributor

codspeed-hq bot commented Feb 9, 2026

Merging this PR will degrade performance by 11.82%

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 32 untouched benchmarks
⏩ 1 skipped benchmark1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
session_store_list[10] 39.4 µs 16.2 µs ×2.4
session_key_to_filename[2026-02-09T12:00:00Z] 870.3 ns 986.9 ns -11.82%

Comparing nanobot (2c7df7a) with main (5783114)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

penso added 2 commits February 9, 2026 14:42
Resolve conflicts:
- CHANGELOG: move WhatsApp entries to [Unreleased] above 0.4.1/0.4.0
- chat.rs: keep Whatsapp in match arm + main's logbook_html/send_text_with_suffix
- style.css: rebuild Tailwind from main's base
- Cargo.lock: regenerate with whatsapp deps on top of main
Resolve conflicts:
- CHANGELOG: WhatsApp entries in [Unreleased] above 0.5.0/0.4.1/0.4.0
- plugin.rs: keep both WhatsApp tests and new DummyOutbound/send_location test
- page-channels.js: merge comment line (CSS mask-image + inline SVG)
- channel.rs: take main's if-let guard instead of unwrap
- chat.rs: separate Telegram arm (main's caption/transcript logic) from
  WhatsApp arm (simpler send_media/send_text with logbook)
- style.css: rebuild Tailwind from main's base
…ecovery

Adapt to workspace-level clippy::unwrap_used and clippy::expect_used
deny lints added in v0.5.0. Replace all 20 .unwrap() calls on
RwLock/Mutex guards with .unwrap_or_else(|e| e.into_inner()) to
gracefully recover from poisoned locks, matching the telegram crate
pattern.
@codecov
Copy link

codecov bot commented Feb 11, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant